export { }

/**
 * 创建一个长度为length的数组，里面的值用value填充
 * @param length 
 * @param value 
 */
// function createArray(length: number, value: any): Array<any> {
//     let result: any[] = [];
//     for (let i = 0; i < length; i++) {
//         result[i] = value
//     }
//     return result
// }
// let result = createArray(3, 'x')
// console.log(result);


// 传入的value 与 数组的类型 是有对应关系的(都为字符串),
// 泛型：<T> 在传入时不确定，在调用时才确定(27行指定)
function createArray<T>(length: number, value: T): Array<T> {
    let result: any[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value
    }
    return result
}
let result = createArray<string>(3, 'x')
console.log(result);



// 类数组-如果一个对象实现了接口，那么就说Symbol值可以被for...of(迭代)
// function sum() {
//     let args: IArguments = arguments;
//     for (let i = 0; i < args.length; i++) {
//         console.log(args[i]);
//     }
// }
// sum(1, 2, 3);
// ----此处未实现，需查阅后再更新


// 泛型-类
class MyArray<T> {
    private list: T[] = []
    add(value: T) {
        this.list.push(value)
    }
    getMax(): T {
        return this.list[0];
    }
}
let array = new MyArray<number>();
array.add(1);
array.add(2);
array.add(3);
console.log(array.getMax());



// 泛型-new
// new之后返回一个泛型，那么定义它的类型也为泛型
function factory<T>(type: { new(): T }): T {
    return new type();
}
class Person { }
let p = factory<Person>(Person);
console.log(p);


// 泛型-接口
// interface Calculate {
//     // 接收一个泛型T,a为T,b也为T,返回结果也为泛型T
//     <T>(a: T, b: T): T
// }
// let sum: Calculate = function <T>(a: T, b: T): T {
//     return a;
//     // return a + b;   //运算符“+”不能应用于类型“T”和“T”。
//     // 如果非要在函数中相加,可以使用下面方法-----------------------
// }
// sum<number>(1, 2);



// 当泛型在接口名后时,在调用接口时，类型就要确定下来,上方处在调用sum时再确定即可。
interface Calculate<T> {
    // 接收一个泛型T,a为T,b也为T,返回结果也为泛型T
    (a: T, b: T): T
}
let sum: Calculate<number> = function <T>(a: T, b: T): T {
    return a;
    // return a + b;   //运算符“+”不能应用于类型“T”和“T”。
    // 如果非要在函数中相加,可以使用下面方法-----------------------
}
sum(1, 2);



// 泛型-可以写多个




// 默认泛型
interface T2<T = string> { // 如 = string不写,需要在下方实例化T2时指定类型

}

type T22 = T2;



// 泛型约束
interface LengthWish {
    length: number
}

function logger2<T extends LengthWish>(val: T) {
    console.log(val.length);
}
logger2<string>('a');

// logger2<number>(111); //类型“number”不满足约束“LengthWish”。
// 结论：定义泛型时，会通过指向的泛型增加约束，当不满足条件时即会报错.
let obj = {
    length: 10
}
type Obj = typeof obj;
logger2<Obj>(obj);


// 类的兼容性:根据形状来判断，跟extends继承没有关系。
// class GrandFather {

// }

// class Father extends GrandFather {

// }

// class Child extends Father {

// }


// // 此处extends是约束的意思,或说T能赋值给Father
// function get<T extends Father>() {

// }


// 此时,由于GrandFather/Father/Child都为空对象,所以传入哪个,都不会报错,因为此时三个类形状是一样的

class GrandFather {
    grandFather!: string;
}

class Father extends GrandFather {
    father!: string;
}

class Child extends Father {
    child!: string;
}


// 此处extends是约束的意思,或说T能赋值给Father
function get<T extends Father>() {

}
// get<GrandFather>(); //报错： 类型 "GrandFather" 中缺少属性 "father"，但类型 "Father" 中需要该属性。
get<Father>();  //Father中包含father属性
get<Child>();   //Child中也包含father属性(继承自Father)


let father = new Father();
let child = new Child();
father = child;   //可以将child赋值给father
//child = father  //报错：类型 "Father" 中缺少属性 "child"，但类型 "Child" 中需要该属性。



// 泛型-接口



// 泛型-类型别名
type Cart<T> = { list: T[] } | T[];
let c1: Cart<string> = { list: ['1'] };
let c2: Cart<number> = [1, 2, 3];

// interface 和 type区别



// 结论：能用接口实现的，不要使用type




// redux-compose重载案例讲解
